home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / UUPC11QS.ARJ / ADDRESS.C next >
C/C++ Source or Header  |  1991-12-07  |  19KB  |  490 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    a d d r e s s . c                                               */
  3. /*                                                                    */
  4. /*    Address parsing routines for UUPC/extended                      */
  5. /*--------------------------------------------------------------------*/
  6.  
  7. #include <ctype.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <stdlib.h>
  11. #include <sys/types.h>
  12.  
  13. #include "lib.h"
  14. #include "address.h"
  15. #include "hostable.h"
  16. #include "security.h"
  17.  
  18. /*--------------------------------------------------------------------*/
  19. /*                          Global variables                          */
  20. /*--------------------------------------------------------------------*/
  21.  
  22. currentfile();
  23.  
  24. /*--------------------------------------------------------------------*/
  25. /*    u s e r _ a t _ n o d e                                         */
  26. /*                                                                    */
  27. /*    break a UUCP path or RFC-822 address into the basic user and    */
  28. /*    node components                                                 */
  29. /*                                                                    */
  30. /*    Note:    This routine assume an address of the form             */
  31. /*             path!node1!user@node2 is for a user@node1 routed via   */
  32. /*             node2 and then path.                                   */
  33. /*--------------------------------------------------------------------*/
  34.  
  35. void user_at_node(const char *raddress,
  36.                   char *hispath,
  37.                   char *hisnode,
  38.                   char *hisuser)
  39. {
  40.  
  41.    static char *saveaddr = NULL;
  42.    static char *savepath;
  43.    static char *savenode;
  44.    static char *saveuser;
  45.  
  46.    char *uptr;                      /* Pointer to his user id              */
  47.    char *nptr;                      /* Pointer to his node id              */
  48.    char *pptr;                      /* Pointer to next node in path to him */
  49.    char *tptr;                      /* Temporary token pointer             */
  50.    char *address;
  51.  
  52.    struct HostTable *Hptr = NULL;   /* Pointer to host name table          */
  53.  
  54. /*--------------------------------------------------------------------*/
  55. /*                     Determine if local address                     */
  56. /*--------------------------------------------------------------------*/
  57.  
  58.    if (!strpbrk(raddress,"!@"))     /* Any host delimiters?                */
  59.    {                                /* No --> report local data            */
  60.       strcpy(hisuser,raddress);
  61.       strcpy(hisnode,nodename);
  62.       strcpy(hispath,nodename);
  63.       strcpy(hisuser,raddress);
  64.       printmsg(5,"user_at_node: Address '%s' is local",raddress);
  65.       return;
  66.    }
  67.  
  68. /*--------------------------------------------------------------------*/
  69. /*    If the current address is the same as the last processed remote */
  70. /*    address, then return the same information as what we determined */
  71. /*    last time.                                                      */
  72. /*--------------------------------------------------------------------*/
  73.  
  74.    if ((saveaddr != NULL) && equal(raddress,saveaddr))
  75.    {
  76.       strcpy(hispath,savepath);
  77.       strcpy(hisnode,savenode);
  78.       strcpy(hisuser,saveuser);
  79.       return;
  80.    }
  81.  
  82. /*--------------------------------------------------------------------*/
  83. /*   The address is different; save the new address and then proceed  */
  84. /*   to parse it.                                                     */
  85. /*--------------------------------------------------------------------*/
  86.  
  87.    address = strdup(raddress);   /* Copy address for parsing         */
  88.    checkref(address);            /* Verify allocation worked         */
  89.  
  90.    if (saveaddr != NULL)         /* Was the data previously allocated?  */
  91.    {                             /* Yes --> Free it                     */
  92.       free(saveaddr);
  93.       free(savepath);
  94.       free(saveuser);
  95.       free(savenode);
  96.    }
  97.  
  98.    saveaddr = strdup(address);   /* Remember address for next pass   */
  99.  
  100.    nptr = nil(char);             /* No known node for user           */
  101.    pptr = mailserv;              /* Default routing via mail server  */
  102.    tptr = address;               /* Remember start of address        */
  103.  
  104. /*--------------------------------------------------------------------*/
  105. /*  The address may be RFC-822 syntax; attempt to parse that format   */
  106. /*--------------------------------------------------------------------*/
  107.  
  108.    while (*tptr == '@')        /* Explicit RFC 822 path?              */
  109.    {
  110.       char *tpath = strtok(++tptr,",:");
  111.       tptr = strtok(NULL,"");
  112.       pptr = HostPath( tpath , pptr );
  113.       printmsg(9,"user_at_node: RFC-822 explicit path: \"%s\" via \"%s\"",
  114.          tptr, pptr);
  115.    } /* while */
  116.  
  117. /*--------------------------------------------------------------------*/
  118. /*   If the user had an RFC-822 path, then the pointer to the path is */
  119. /*   now initialized, and the remainder of the path has been dropped  */
  120. /*   from *tptr; otherwise, the entire address is found via *tptr     */
  121. /*--------------------------------------------------------------------*/
  122.  
  123.    uptr  = strtok(tptr,"@");   /* Get user part of userid @node       */
  124.    tptr  = strtok(NULL,"@");   /* Get node part of userid @node       */
  125.  
  126.    if (tptr != NULL)           /* Did we get a node?                  */
  127.    {                           /* Yes --> Save it                     */
  128.       nptr = tptr;
  129.       pptr = HostPath( nptr, pptr);
  130.    } /* if */
  131.  
  132. /*--------------------------------------------------------------------*/
  133. /*   Now, we will try stripping off any uucp path that the address    */
  134. /*   may have acquired; we'll assume the last node is the addressee's */
  135. /*   node.                                                            */
  136. /*--------------------------------------------------------------------*/
  137.  
  138.    uptr = strtok(uptr,"!");
  139.    tptr = strtok(NULL,"");
  140.  
  141.    while ( tptr != NULL )
  142.    {
  143.       nptr = uptr;
  144.       uptr = strtok(tptr,"!");
  145.       tptr = strtok(NULL,"");
  146.       pptr = HostPath( nptr, pptr);
  147.    } /* while */
  148.  
  149. /*--------------------------------------------------------------------*/
  150. /*   Finally, we parse off any internet mail that used the infamous % */
  151. /*   hack (user%node1@gatewayb)                                       */
  152. /*--------------------------------------------------------------------*/
  153.  
  154.    while ((tptr = strrchr(uptr,'%')) != NULL)   /* Get last percent  */
  155.    {
  156.       *tptr = '@';               /* Make it an RFC-822 address       */
  157.       uptr  = strtok(uptr,"@");  /* Get user part of userid @node    */
  158.       nptr  = strtok(NULL,"@");  /* Get node part of userid @node    */
  159.       pptr  = HostPath(nptr, pptr); /* Old node is new path          */
  160.    } /* while */
  161.  
  162. /*--------------------------------------------------------------------*/
  163. /*   If the last known hop in the path is via our own system, but the */
  164. /*   target node is not our own system, route the message via our     */
  165. /*   default mail server.                                             */
  166. /*--------------------------------------------------------------------*/
  167.  
  168.    nptr = HostAlias( nptr );
  169.    if (equali(pptr,nodename))
  170.                               /* Is mail routed via our local system? */
  171.    {                          /* Yes --> Determine if destined for us */
  172.       Hptr = checkname(nptr);          /* Locate the system       */
  173.       if (Hptr == BADHOST)             /* System known?           */
  174.       {                                /* No --> Route default    */
  175.          printmsg(5,
  176.             "user_at_node: Routing mail for \"%s\" via default mail server",
  177.                   nptr);
  178.          pptr = mailserv;
  179.       } /* if */
  180.    }  /* if */
  181.  
  182. /*--------------------------------------------------------------------*/
  183. /*                         Print our results                          */
  184. /*--------------------------------------------------------------------*/
  185.  
  186.    printmsg(9,
  187.          "user_at_node: Address \"%s\" is \"%s\" at \"%s\" via \"%s\"",
  188.             raddress, uptr, nptr, pptr);
  189.  
  190. /*--------------------------------------------------------------------*/
  191. /*  We have parsed the address.  Fill in the information for caller   */
  192. /*--------------------------------------------------------------------*/
  193.  
  194.    strcpy(hispath,pptr);
  195.    strcpy(hisnode,nptr);
  196.    strcpy(hisuser,uptr);
  197.  
  198. /*--------------------------------------------------------------------*/
  199. /*   Save the parsed information along with the original address we   */
  200. /*   were passed in.  This could save breaking it down again.         */
  201. /*--------------------------------------------------------------------*/
  202.  
  203.    savepath = strdup(hispath);
  204.    savenode = strdup(hisnode);
  205.    saveuser = strdup(hisuser);
  206.  
  207.    free(address);
  208. }  /* user_at_node */
  209.  
  210.  
  211. /*--------------------------------------------------------------------*/
  212. /*    H o s t A l i a s                                               */
  213. /*                                                                    */
  214. /*    Resolve a host alias to its real canonized name                 */
  215. /*--------------------------------------------------------------------*/
  216.  
  217. char *HostAlias( char *input)
  218. {
  219.    size_t loop = 100;
  220.    struct HostTable *Hptr;
  221.    char *host = input;
  222.  
  223.    do {
  224.       Hptr = checkname(host);
  225.       if (Hptr == BADHOST)
  226.          break;
  227.       else {
  228.          if (--loop == 0)
  229.          {
  230.             printmsg(0,"HostAlias: Alias loop of \"%s\" and \"%s\"",
  231.                      host , Hptr->via);
  232.             break;
  233.          } /* if */
  234.  
  235.          if (Hptr->hstatus == localhost)  /* local system?     */
  236.             host = nodename;              /* Yes --> Give std. name  */
  237.          else if (Hptr->hstatus == aliasof)
  238.             host = Hptr->via;
  239.          else if ( Hptr->hostname[0] != '*') /* Ignore wildcards     */
  240.             host = Hptr->hostname;
  241.       } /* if */
  242.    } while( Hptr->hstatus == aliasof);
  243.  
  244.    printmsg((input == host) ? 10: 5 ,
  245.             "HostAlias: \"%s\" is alias of \"%s\"",input,host);
  246.    return host;
  247. } /* HostAlias */
  248.  
  249. /*--------------------------------------------------------------------*/
  250. /*    H o s t P a t h                                                 */
  251. /*                                                                    */
  252. /*    Determine the path to a host                                    */
  253. /*--------------------------------------------------------------------*/
  254.  
  255. char *HostPath( char *input, char *best)
  256. {
  257.    size_t loop = 100;
  258.    struct HostTable *Hptr;
  259.    char *host = input;
  260.  
  261.    do {
  262.       Hptr = checkname(host);
  263.       if (Hptr == BADHOST)
  264.          break;
  265.       else {
  266.          if (--loop == 0)
  267.          {
  268.             printmsg(0,"HostPath: Path loop of \"%s\" and \"%s\"",
  269.                      host , Hptr->via);
  270.             break;
  271.          } /* if */
  272.          if (Hptr->hstatus == localhost)  /* local system?     */
  273.             best = nodename;
  274.          else if (Hptr->hstatus == gatewayed)  /* Gatewayed?   */
  275.             best = Hptr->hostname;      /* Yes --> Use name for path */
  276.          else {
  277.             host = Hptr->via;
  278.             if ( checkreal( host ) != BADHOST )
  279.                best = host;
  280.          } /* else */
  281.       } /* else */
  282.    } while( (Hptr->hstatus == aliasof) ||
  283.             (Hptr->hstatus == routed));
  284.  
  285.    printmsg((best == mailserv) ? 10 : 5 ,
  286.          "HostPath: \"%s\" routed via \"%s\"", input, best);
  287.    return best;
  288. } /* HostPath */
  289.  
  290. /*--------------------------------------------------------------------*/
  291. /*    E x t r a c t A d d r e s s                                     */
  292. /*                                                                    */
  293. /*    Returns the user name (if available and requested or            */
  294. /*    E-mail address of the user                                      */
  295. /*                                                                    */
  296. /*    Written by ahd 15 July 1989                                     */
  297. /*--------------------------------------------------------------------*/
  298.  
  299. char *ExtractAddress(char *result,
  300.                     const char *input ,
  301.                     FULLNAME fullname)
  302. {
  303.    char *nonblank = NULL;
  304.    char *column  = (char *) input;
  305.    char name[BUFSIZ];      /* User full name             */
  306.    char *nameptr = name;
  307.    char addr[BUFSIZ];      /* User e-mail address        */
  308.    char *addrptr  = addr;
  309.  
  310.    char state = 'A';                /* State = skip whitespace    */
  311.    char newstate = 'A';             /* Next state to process      */
  312.    int bananas = 0;                 /* No () being processed now  */
  313.    boolean quoted = FALSE;
  314.  
  315. /*--------------------------------------------------------------------*/
  316. /*   Begin loop to copy the input field into the address and or the   */
  317. /*   user name.  We will begin by copying both (ignoring whitespace   */
  318. /*   for addresses) because we won't know if the input field is an    */
  319. /*   address or a name until we hit either a special character of     */
  320. /*   some sort.                                                       */
  321. /*--------------------------------------------------------------------*/
  322.  
  323.    while ((*column != '\0') && (state != ','))
  324.    {
  325.       switch (state) {
  326.          case 'A':
  327.             if (isspace(*column))   /* Found first non-blank? */
  328.                break;               /* No --> keep looking    */
  329.             nonblank = column;
  330.             state = 'B';
  331.                                     /* ... and fall through          */
  332.          case 'B':
  333.          case ')':
  334.             newstate = *column;
  335.             switch(*column) {
  336.                case '(':
  337.                   bananas++;
  338.                   break;
  339.  
  340.                case '"':
  341.                   break;
  342.  
  343.                case '<':
  344.                   addrptr = addr;   /* Start address over      */
  345.                   nameptr = name;   /* Start name over again   */
  346.                   column  = nonblank - 1;
  347.                                     /* Re-scan in new state    */
  348.                   newstate = '>';   /* Proc all-non <> as name */
  349.                   break;            /* Begin addr over again   */
  350.                case ',':
  351.                   break;            /* Terminates address      */
  352.                case '>':
  353.                case ')':
  354.                   printmsg(0,"Invalid RFC-822 address: %s",nonblank);
  355.                   panic();          /* Ooops, funky address    */
  356.                   break;
  357.  
  358.                default:
  359.                   newstate = state; /* stay in this state            */
  360.                   if (!isspace(*column))
  361.                      *(addrptr++) = *column;
  362.             }  /* switch(*column) */
  363.             break;
  364.  
  365.          case '<':   if (*column == '>')
  366.                         newstate = '>';
  367.                      else if (!isspace(*column))
  368.                         *(addrptr++) = *column;
  369.                      break;
  370.  
  371.          case '>':   if (*column == '<')
  372.                         newstate = '<';
  373.                      else switch( *column )
  374.                      {
  375.                         case ')':
  376.                            if (quoted)
  377.                               *(nameptr++) = *column;
  378.                            else
  379.                               bananas--;
  380.                            break;
  381.  
  382.                         case '(':
  383.                            if (quoted)
  384.                               *(nameptr++) = *column;
  385.                            else
  386.                               bananas++;
  387.                            break;
  388.  
  389.                         case '"':
  390.                            if (bananas == 0)
  391.                            {
  392.                               quoted = !quoted;
  393.                               break;
  394.                            }
  395.                            /* else fall through */
  396.  
  397.                         default:
  398.                            *(nameptr++) = *column;
  399.                      } /* switch */
  400.                      break;
  401.  
  402.          case '(':   if (*column == '(')
  403.                         ++bananas;
  404.                      else if (*column == ')')
  405.                      {
  406.                         if (--bananas == 0)
  407.                         {
  408.                            newstate = ')';
  409.                            break;
  410.                         }
  411.                      }
  412.                      else
  413.                         *(nameptr++) = *column;
  414.                      break;
  415.  
  416.          case '"':   if (*column == '"')
  417.                         newstate = ')';
  418.                      else
  419.                         *(nameptr++) = *column;
  420.  
  421.                      break;
  422.  
  423.          default:    panic();
  424.                                  /* Logic error, bad state        */
  425.                      break;
  426.  
  427.       }  /* switch (state) */
  428.       state = newstate;
  429.       column++;
  430.    } /* while */
  431.  
  432.  
  433. /*--------------------------------------------------------------------*/
  434. /*                   Verify we retrieved an address                   */
  435. /*--------------------------------------------------------------------*/
  436.  
  437.    if (state == 'A')
  438.    {
  439.       printmsg(0, "ExtractAddress: Could find not address in \"%s\"",
  440.                column);
  441.       panic();
  442.    }
  443.  
  444. /*--------------------------------------------------------------------*/
  445. /*                 Fill in the results for the caller                 */
  446. /*--------------------------------------------------------------------*/
  447.  
  448.    *addrptr = '\0';
  449.    *nameptr = '\0';
  450.    *result  = '\0';
  451.    if ((fullname == ADDRESSONLY) ||
  452.        ((fullname == FULLADDRESS) && (state == 'B')))
  453.        strcpy(result,addr);         /* Return the full address    */
  454.    else if (state != 'B')
  455.    {
  456.       while (--nameptr >= name)
  457.       {
  458.          if (isspace(*nameptr))
  459.             *nameptr = '\0';
  460.          else
  461.             break;
  462.       }
  463.  
  464. /*--------------------------------------------------------------------*/
  465. /*               Strip leading blanks from the address                */
  466. /*--------------------------------------------------------------------*/
  467.  
  468.       nameptr = name;
  469.       while (isspace(*nameptr))
  470.          nameptr++;
  471.       if ( fullname == FULLADDRESS )
  472.          sprintf( result , "\"%s\" <%s>", nameptr, addr );
  473.       else
  474.          strcpy(result,nameptr);
  475.    } /* else */
  476.  
  477.    printmsg(4,"ExtractAddress: %s into <%s> \"%s\"",
  478.             nonblank,addr,(fullname) ? result : name);
  479.  
  480. /*--------------------------------------------------------------------*/
  481. /*   Return the position of the next address, if any, to the caller   */
  482. /*--------------------------------------------------------------------*/
  483.  
  484.    if ( *column == '\0')
  485.       return NULL;
  486.    else
  487.       return column + 1;
  488.  
  489. } /*ExtractAddress*/
  490.